using System;
using System.Collections.Generic;

namespace KodeIT.Web
{
    /// <summary>
    /// This class represents the collection that provides access to the request and response headers.
    /// </summary>
    public class HttpHeaders
    {
        private NativeContext _nativeContext;
        private Dictionary<string, string> _setCollection;
        private Dictionary<string, string> _getCollection;

        internal HttpHeaders(NativeContext nativeContext, Dictionary<string, string> setCollection)
        {
            _nativeContext = nativeContext;
            _setCollection = setCollection;
            _getCollection = new Dictionary<string, string>(NativeMethods.MIN_HEADER_COUNT);
        }

        private void ThrowOnBadFormat(string headerName)
        {
            if( 
                !headerName.Equals(HttpHeader.Method) && 
                !headerName.Equals(HttpHeader.Url) && 
                !headerName.Equals(HttpHeader.Version) && 
                !headerName.EndsWith(":")
                )
            {
                throw new MalformedHeaderException(headerName);
            }
        }

        /// <summary>
        /// Returns the value of an http request or response header.
        /// </summary>
        /// <param name="name">The name of the http header. It must end with a colon (:).</param>
        /// <returns>The value of the http header.</returns>
        public string Get(string name)
        {
            ThrowOnBadFormat(name);

            if (!_getCollection.ContainsKey(name))
            {
                _getCollection[name] = NativeMethods.GetHeader(_nativeContext, name);
            }

            return _getCollection[name];
        }

        private void AddSet(string name, string value)
        {
            ThrowOnBadFormat(name);

            _setCollection[name] = value;
            _getCollection[name] = value;
        }

        /// <summary>
        /// Adds an http header name and value to the request or response.
        /// </summary>
        /// <param name="name">The name of the http header. It must end with a colon (:).</param>
        /// <param name="value">The value of the http header.</param>
        public void Add(string name, string value)
        {
            AddSet(name, value);
        }

        /// <summary>
        /// Updates an http header value in the request or response.
        /// </summary>
        /// <param name="name">The name of the http header. It must end with a colon (:).</param>
        /// <param name="value">The value of the http header.</param>
        public void Set(string name, string value)
        {
            AddSet(name, value);
        }

        /// <summary>
        /// Removes an http header fromt he request or response.
        /// </summary>
        /// <param name="name">The name of the http header. It must end with a colon (:).</param>
        public void Remove(string name)
        {
            ThrowOnBadFormat(name);

            _setCollection[name] = String.Empty;
            _getCollection[name] = String.Empty;
        }

        /// <summary>
        /// Gets or sets the value of an http header.
        /// </summary>
        /// <param name="name">The name of the http header. It must end with a colon (:).</param>
        /// <returns>The value of the http header.</returns>
        public string this[string name]
        {
            get { return Get(name); }
            set { Set(name, value); }
        }
    }
}
